package freespiritsocial.io.user.ui.fragment.search

import android.Manifest
import android.os.Bundle
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.permissionx.guolindev.PermissionX
import freespiritsocial.io.user.R
import freespiritsocial.io.user.base.BaseFragment
import freespiritsocial.io.user.data.model.bean.PlaceAutocompleteBean
import freespiritsocial.io.user.databinding.FrgSearchLocationBinding
import freespiritsocial.io.user.ext.clearData
import freespiritsocial.io.user.ext.init
import freespiritsocial.io.user.ext.setTitle
import freespiritsocial.io.user.handle.BackHandle
import freespiritsocial.io.user.ui.adapter.LocationAdapter
import freespiritsocial.io.user.ui.helper.GoogleApiHelper
import freespiritsocial.io.user.util.CacheUtil
import freespiritsocial.io.user.viewmodel.LocationViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import me.hgj.jetpackmvvm.ext.nav
import me.hgj.jetpackmvvm.network.manager.NetState
import me.hgj.jetpackmvvm.network.manager.NetworkStateManager

/**
 * @description 搜索地址
 */
@ExperimentalCoroutinesApi
class SearchLocationFrg: BaseFragment<LocationViewModel,FrgSearchLocationBinding>() {

    private val googleApiHelper by lazy(LazyThreadSafetyMode.NONE) {
        GoogleApiHelper(requireContext())
    }
    private val locationAdapter by lazy(LazyThreadSafetyMode.NONE) {
        LocationAdapter().apply {
            setOnItemClickListener { _,_,position ->
                val orNull = data.getOrNull(position)
                val id = orNull?.placeId ?: return@setOnItemClickListener
                getPlace(id,orNull.type)
            }
        }
    }
    private val nearbyPlacesAdapter by lazy(LazyThreadSafetyMode.NONE) {
        LocationAdapter(20).apply {
            setOnItemClickListener { _,_,position ->
                val orNull = data.getOrNull(position)
                val id = orNull?.placeId ?: return@setOnItemClickListener
                getPlace(id,orNull.type)
            }
        }
    }

    override fun layoutId(): Int = R.layout.frg_search_location

    override fun initView(savedInstanceState: Bundle?) = with(mDatabind) {
        mViewModel.googleApiHelper = googleApiHelper
        model = mViewModel
        click = Click()
        recyclerResult.init(locationAdapter,emptyText = "Address not found.",emptyImage = R.mipmap.empty_search)
        listNearbyPlaces.init(nearbyPlacesAdapter)
        locationAdapter.emptyLayout?.isVisible = false
        root.setTitle(getString(R.string.location))
    }

    override fun lazyLoadData() {
        super.lazyLoadData()
        onNetworkStateChanged(NetworkStateManager.instance.mNetworkStateCallback.value ?: return)
    }

    override fun createObserver() {
        super.createObserver()
        mViewModel.searchText.observe(this) {
            mViewModel.search()
            locationAdapter.keyword = it
            locationAdapter.data.clear()
            if (it.isEmpty()) {
                locationAdapter.notifyDataSetChanged()
                mDatabind.groupNearbyPlaces.isVisible = true
            }
        }
        mViewModel.googleSearchResultNetWork.observe(this) {
            locationAdapter.emptyLayout?.isVisible = true
            if (it.placeId.isNullOrEmpty().not()) {
                locationAdapter.addData(it)
                mDatabind.groupNearbyPlaces.isVisible = false
            } else
                locationAdapter.notifyDataSetChanged()
        }
        appViewModel.locationPlace.observe(this) {
            mDatabind.tvSuggestedLocation.text = it.address
            mDatabind.tvSuggestedLocation.tag = it.id
        }
        appViewModel.locationPermission.observe(this) { hasPermission ->
            mDatabind.groupError.isVisible = hasPermission.not()
            mViewModel.errorText.set("Positioning permission is not\nturned on.")
            mViewModel.errorBtnText.set(getString(R.string.go_to_set))
            mDatabind.groupResult.isVisible = hasPermission

            if (hasPermission.not()) return@observe

            val placeItem1 = arguments?.getParcelable("place") ?: CacheUtil.getCurPlace()
            placeItem1?.let { placeItem ->
                mDatabind.tvSuggestedLocation.text = placeItem.address
                mDatabind.tvSuggestedLocation.tag = placeItem.id
                mViewModel.nearbySearch(placeItem.latLng.latitude,placeItem.latLng.longitude) {
                    nearbyPlacesAdapter.clearData()
                    nearbyPlacesAdapter.addData(it)
                    mDatabind.groupNearbyPlaces.isVisible = true
                }
            }
        }
    }

    override fun onNetworkStateChanged(netState: NetState) {
        mDatabind.groupError.isVisible = netState.isSuccess.not()
        mDatabind.groupResult.isVisible = netState.isSuccess
        mDatabind.groupNearbyPlaces.isVisible = netState.isSuccess && mDatabind.groupResult.isVisible.not()
        mViewModel.errorText.set("Failed to get location, please check\ncurrent network")
        mViewModel.errorBtnText.set("Reacquire")
    }

    override fun onDestroyView() {
        googleApiHelper.onDestroy()
        super.onDestroyView()
    }

    private fun toConfirmPermission() {
        val permissionList = ArrayList<String>()
        permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION)
        permissionList.add(Manifest.permission.ACCESS_COARSE_LOCATION)
        PermissionX.init(this).permissions(
            permissionList
        ).request { _,grantedList,_ ->
            val contains = grantedList.contains(Manifest.permission.ACCESS_FINE_LOCATION)
            appViewModel.locationPermission.postValue(contains)
        }
    }


    inner class Click: BackHandle {
        override fun goBack() {
            nav().navigateUp()
        }

        fun removeSearch() {
            mViewModel.searchText.value = ""
        }

        fun getCurLocation() {
            val id = mDatabind.tvSuggestedLocation.tag as? String ?: return
            getPlace(id,PlaceAutocompleteBean.Place_API)
        }

        fun goToSet() {
            if (mViewModel.errorBtnText.get() != "Reacquire") {
                toConfirmPermission()
            }
        }

    }

    private fun getPlace(id: String,apiType: Int) {
        showLoading()
        lifecycleScope.launch(Dispatchers.IO) {
            googleApiHelper.fetchPlace(id) {
                eventViewModel.placeSelectEvent.postValue(it to apiType)
                dismissLoading()
                nav().navigateUp()
            }
        }
    }
}